#region Copyright (c) 2006-2009 Widgetsphere LLC, All Rights Reserved
//--------------------------------------------------------------------- *
//                          Widgetsphere  LLC                           *
//             Copyright (c) 2006-2009 All Rights reserved              *
//                                                                      *
//                                                                      *
//This file and its contents are protected by United States and         *
//International copyright laws.  Unauthorized reproduction and/or       *
//distribution of all or any portion of the code contained herein       *
//is strictly prohibited and will result in severe civil and criminal   *
//penalties.  Any violations of this copyright will be prosecuted       *
//to the fullest extent possible under law.                             *
//                                                                      *
//THE SOURCE CODE CONTAINED HEREIN AND IN RELATED FILES IS PROVIDED     *
//TO THE REGISTERED DEVELOPER FOR THE PURPOSES OF EDUCATION AND         *
//TROUBLESHOOTING. UNDER NO CIRCUMSTANCES MAY ANY PORTION OF THE SOURCE *
//CODE BE DISTRIBUTED, DISCLOSED OR OTHERWISE MADE AVAILABLE TO ANY     *
//THIRD PARTY WITHOUT THE EXPRESS WRITTEN CONSENT OF WIDGETSPHERE LLC   *
//                                                                      *
//UNDER NO CIRCUMSTANCES MAY THE SOURCE CODE BE USED IN WHOLE OR IN     *
//PART, AS THE BASIS FOR CREATING A PRODUCT THAT PROVIDES THE SAME, OR  *
//SUBSTANTIALLY THE SAME, FUNCTIONALITY AS ANY WIDGETSPHERE PRODUCT.    *
//                                                                      *
//THE REGISTERED DEVELOPER ACKNOWLEDGES THAT THIS SOURCE CODE           *
//CONTAINS VALUABLE AND PROPRIETARY TRADE SECRETS OF WIDGETSPHERE,      *
//INC.  THE REGISTERED DEVELOPER AGREES TO EXPEND EVERY EFFORT TO       *
//INSURE ITS CONFIDENTIALITY.                                           *
//                                                                      *
//THE END USER LICENSE AGREEMENT (EULA) ACCOMPANYING THE PRODUCT        *
//PERMITS THE REGISTERED DEVELOPER TO REDISTRIBUTE THE PRODUCT IN       *
//EXECUTABLE FORM ONLY IN SUPPORT OF APPLICATIONS WRITTEN USING         *
//THE PRODUCT.  IT DOES NOT PROVIDE ANY RIGHTS REGARDING THE            *
//SOURCE CODE CONTAINED HEREIN.                                         *
//                                                                      *
//THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE.              *
//--------------------------------------------------------------------- *
#endregion
using System;
using System.Drawing;
using System.Collections;
using Widgetsphere.Generator.Common.GeneratorFramework;
using System.Windows.Forms;
using Widgetsphere.Generator.Common.Util;
using Widgetsphere.Generator.Common.Forms;
using System.Xml;
using System.Collections.ObjectModel;
using Widgetsphere.Generator.Forms;

namespace Widgetsphere.Generator.Models
{
	public class ColumnCollectionController : BaseModelObjectController
	{
		#region Member Variables

    private ContextMenu PopupMenu = null;
    private ListView ControllerListView = null;

		#endregion

    #region Constructor

    protected internal ColumnCollectionController(IModelObject modelObject)
      : base(modelObject)
    {
    }

    #endregion

		#region BaseModelObjectController Members

		public override ModelObjectTreeNode Node
		{
			get
			{
				if(_node == null)
				{
					_node = new ColumnCollectionNode(this);
				}
				return _node;
			}
		}

		public override ModelObjectUserInterface UIControl
		{
			get
			{
				try
				{
					if (this.UserInterface == null)
					{
						PanelUIControl ctrl = new PanelUIControl();
						ControllerListView = new ListView();
						ControllerListView.View = View.Details;
						ControllerListView.HideSelection = false;
						ControllerListView.FullRowSelect = true;
						ControllerListView.Dock = DockStyle.Fill;
						ControllerListView.Columns.Add("Name", 100, HorizontalAlignment.Left);
						ControllerListView.Columns.Add("Code Facade", 100, HorizontalAlignment.Left);
						ControllerListView.Columns.Add("Primary Key", 100, HorizontalAlignment.Left);
						ControllerListView.Columns.Add("Allow Null", 100, HorizontalAlignment.Left);
						ControllerListView.Columns.Add("Type", 100, HorizontalAlignment.Left);
						ControllerListView.Columns.Add("Length", 50, HorizontalAlignment.Right);
						System.Type[] typeList = new System.Type[] { typeof(string), typeof(string), typeof(string), typeof(string), typeof(string), typeof(int) };
						ListViewComparer comparer = new ListViewComparer(ControllerListView, typeList);
						ControllerListView.ListViewItemSorter = comparer;
						comparer.Column = 0;
						ControllerListView.Sorting = SortOrder.Ascending;
						ControllerListView.SmallImageList = Widgetsphere.Generator.ImageHelper.GetImageList();
						ctrl.MainPanel.Controls.Add(ControllerListView);
						ctrl.Dock = DockStyle.Fill;

						ControllerListView.Sort();
						ControllerListView.MouseUp += new MouseEventHandler(listView_MouseUp);
						ControllerListView.KeyUp += new KeyEventHandler(listView_KeyUp);
						ControllerListView.DoubleClick += new EventHandler(listView_DoubleClick);

						try
						{
							if (((ReferenceCollection)this.Object).Parent is Table)
							{
								PopupMenu = new ContextMenu();
								ControllerListView.ContextMenu = PopupMenu;
								MenuItem menuDelete = new MenuItem("DeleteX");
								menuDelete.Click += new EventHandler(menuDelete_Click);
								PopupMenu.MenuItems.Add(menuDelete);
							}
						}
						catch (Exception ex)
						{							
							throw;
						}

						this.UserInterface = ctrl;
					}

					//Load the list
					ControllerListView.Items.Clear();
					foreach (Reference reference in (ReferenceCollection)this.Object)
					{
						Column column = ((Column)reference.Object);
						ListViewItem newItem = new ListViewItem(column.Name);

						bool inRelation = false;
						ReadOnlyCollection<Relation> parentRelations = ((ModelRoot)this.Object.Root).Database.Relations.FindByChildTable((Table)column.ParentTableRef.Object);
						foreach (Relation relation in parentRelations)
						{
							foreach (ColumnRelationship columnRelationship in relation.ColumnRelationships)
							{
								if (columnRelationship.ChildColumnRef.Object == column)
									inRelation = true;
							}
						}

						if (column.PrimaryKey)
							newItem.ImageIndex = ImageHelper.GetImageIndex(ImageConstants.ColumnPrimaryKey);
						else if (inRelation)
							newItem.ImageIndex = ImageHelper.GetImageIndex(ImageConstants.ColumnForeignKey);
						else
							newItem.ImageIndex = ImageHelper.GetImageIndex(ImageConstants.Column);

						newItem.Tag = reference;
						newItem.Name = reference.Key;
						newItem.SubItems.Add(column.CodeFacade);
						newItem.SubItems.Add(column.PrimaryKey.ToString());
						newItem.SubItems.Add(column.AllowNull.ToString());
						newItem.SubItems.Add(column.Type.ToString().ToLower());
						newItem.SubItems.Add(column.Length.ToString());
						ControllerListView.Items.Add(newItem);
					}

					return this.UserInterface;

				}
				catch (Exception ex)
				{					
					throw;
				}

			}
		}

    private void listView_DoubleClick(object sender, System.EventArgs e)
    {
      if (this.ControllerListView.SelectedItems.Count == 1)
      {
        ListViewItem item = this.ControllerListView.SelectedItems[0];
        TreeNode[] nodeList = this.Node.Nodes.Find(((Reference)item.Tag).Key, false);
        if (nodeList.Length > 0)
        {
          if (this.Node.TreeView != null)
            this.Node.TreeView.SelectedNode = nodeList[0];
        }
      }
    }

    private void listView_KeyUp(object sender, KeyEventArgs e)
    {
      if (e.KeyCode == Keys.Delete)
      {
        menuDelete_Click(null, null);
      }
    }

    private void listView_MouseUp(object sender, MouseEventArgs e)
    {
			if (e.Button == MouseButtons.Right)
			{
				if ((PopupMenu != null) && PopupMenu.MenuItems.Count > 0)
					PopupMenu.Show((ListView)sender, new Point(e.X, e.Y));
			}
    }

    private void menuDelete_Click(object sender, System.EventArgs e)
    {
      if (MessageBox.Show("Do you wish to delete the selected items?", "Delete?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
        return;

      foreach(ListViewItem item in ControllerListView.SelectedItems)
        ((ReferenceCollection)this.Object).Remove(((Reference)item.Tag));

      //Remove the item from the listview
      for(int ii = ControllerListView.SelectedItems.Count - 1 ; ii >= 0 ; ii--)
      {
        //Remove the item from the tree
        this.Node.Nodes.Remove(this.Node.Nodes[ControllerListView.SelectedItems[ii].Name]);
        //Remove Listitem
        ControllerListView.Items.Remove(ControllerListView.SelectedItems[ii]);
      }

      this.Object.Root.Dirty = true;

    }

		public override MenuCommand[] GetMenuCommands()
		{
			if (this.Node.Parent is TableNode)
			{
				MenuCommand mcAddColumn = new DefaultMenuCommand();
				mcAddColumn.Text = "New Column";
				mcAddColumn.Click += new EventHandler(AddColumnMenuClick);

				MenuCommand menuUpdateColumnName = new DefaultMenuCommand();
				menuUpdateColumnName.Text = "Update Column Names...";
				menuUpdateColumnName.Click += new EventHandler(UpdateColumnNameMenuClick);

				MenuCommand menuUpdateCodeFace = new DefaultMenuCommand();
				menuUpdateCodeFace.Text = "Update Column Codefacades...";
				menuUpdateCodeFace.Click += new EventHandler(UpdateCodefacadeMenuClick);

				MenuCommand menuSep = new DefaultMenuCommand();
				menuSep.Text = "-";

				MenuCommand menuPaste = new DefaultMenuCommand();
				menuPaste.Text = "Paste";
				menuPaste.Click += new EventHandler(PasteMenuClick);

				return new MenuCommand[] { mcAddColumn, menuUpdateColumnName, menuUpdateCodeFace, menuSep, menuPaste };
			}
			else
			{
				return new MenuCommand[] { };
			}
		}

    public override MessageCollection Verify()
    {
      try
      {
        MessageCollection retval = new MessageCollection();
        retval.AddRange(base.Verify());

				if (!(((ReferenceCollection)this.Object).Parent is Table))
					return retval;

				ReferenceCollection referenceCollection = (ReferenceCollection)this.Object;

        //Check for duplicate names
        Hashtable nameList = new Hashtable();
        foreach (Reference reference in referenceCollection)
        {
          Column column = (Column)reference.Object;
          string name = column.Name.ToLower();
          if (nameList.ContainsKey(name))
						retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextDuplicateName, column.Name), this);
          else
            nameList.Add(name, "");
        }

				if (retval.Count == 0)
				{
					//Check for duplicate codefacades
					nameList = new Hashtable();
					foreach (Reference reference in referenceCollection)
					{
						Column column = (Column)reference.Object;
						string name = column.PascalName.ToLower();
						if (nameList.ContainsKey(name))
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextDuplicateCodeFacade, column.Name), this);
						else
							nameList.Add(name, "");
					}
				}

        //Check for a primary key
        bool hasPrimary = false;
        bool isPrimaryNull = false;
        foreach (Reference reference in referenceCollection)
        {
          Column column = (Column)reference.Object;

          if (column.PrimaryKey)
          {
            hasPrimary = true;
            isPrimaryNull |= column.AllowNull;
          }
        }

				//Check for field named created,modfied,timestamp as these are taken				
				foreach (Reference reference in referenceCollection)
				{
					Column column = (Column)reference.Object;
					string name = column.Name.ToLower().Replace("_", "");
					Table t = (Table)column.ParentTableRef.Object;
					if (t.AllowCreateAudit)
					{
						//If there is a CreateAudit then no fields can be named the predined values						
						if (string.Compare(name, ((ModelRoot)column.Root).Database.CreatedByColumnName.Replace("_", ""), true) == 0)
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextPreDefinedNameField, name), this);
						else if (string.Compare(name, ((ModelRoot)column.Root).Database.CreatedDateColumnName.Replace("_", ""), true) == 0)
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextPreDefinedNameField, name), this);
					}
					if (t.AllowModifiedAudit)
					{
						if (string.Compare(name, ((ModelRoot)column.Root).Database.ModifiedByColumnName.Replace("_", ""), true) == 0)
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextPreDefinedNameField, name), this);
						else if (string.Compare(name, ((ModelRoot)column.Root).Database.ModifiedDateColumnName.Replace("_", ""), true) == 0)
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextPreDefinedNameField, name), this);
					}
					if (t.AllowTimestamp)
					{
						if (string.Compare(name, ((ModelRoot)column.Root).Database.TimestampColumnName.Replace("_", ""), true) == 0)
							retval.Add(MessageTypeConstants.Error, string.Format(ValidationHelper.ErrorTextPreDefinedNameField, name), this);
					}
				}

				if (referenceCollection.Count != 0)
				{
					Column testColumn = (Column)referenceCollection[0].Object;
					if (!((Table)testColumn.ParentTableRef.Object).Generated)
						return retval;
					else if (!hasPrimary)
						retval.Add(MessageTypeConstants.Error, ValidationHelper.ErrorTextNoPrimaryKey, ((ModelObjectTreeNode)this.Node.Parent).Controller);
					else if (isPrimaryNull)
						retval.Add(MessageTypeConstants.Error, ValidationHelper.ErrorTextPrimaryKeyNull, ((ModelObjectTreeNode)this.Node.Parent).Controller);
				}
        
        return retval;

      }
      catch (Exception ex)
      {
        throw;
      }
    }

    public override bool DeleteObject()
    {
      return false;
    }

    public override void Refresh()
    {
      this.UserInterface = null;
    }

    #endregion

		#region Menu Handlers

		private void UpdateCodefacadeMenuClick(object sender, System.EventArgs e)
		{
			ColumnCodeFacadeUpdateForm F = new ColumnCodeFacadeUpdateForm((ReferenceCollection)this.Object, null, ColumnCodeFacadeUpdateForm.FieldSettingConstants.CodeFacade);
			F.ShowDialog();
		}

		private void UpdateColumnNameMenuClick(object sender, System.EventArgs e)
		{
			ColumnCodeFacadeUpdateForm F = new ColumnCodeFacadeUpdateForm((ReferenceCollection)this.Object, null, ColumnCodeFacadeUpdateForm.FieldSettingConstants.Name);
			F.ShowDialog();
		}

		private void AddColumnMenuClick(object sender, System.EventArgs e)
		{
			Column column = ((ModelRoot)this.Object.Root).Database.Columns.Add();
			((ReferenceCollection)this.Object).Add(column.CreateRef());
      Reference tableRef = ((Table)((ModelObjectTreeNode)this.Node.Parent).Controller.Object).CreateRef();
      column.ParentTableRef = tableRef;
			this.OnItemChanged(this, new System.EventArgs());
		}

		private void PasteMenuClick(object sender, System.EventArgs e)
		{
			if (Clipboard.ContainsData("ws.model.column"))
			{
				XmlDocument document = new XmlDocument();
				document.LoadXml((string)Clipboard.GetData("ws.model.column"));

				Column column = ((ModelRoot)this.Object.Root).Database.Columns.Add();
				int id = column.Id;
				column.XmlLoad(document.DocumentElement);
				column.SetId(id);
				((ReferenceCollection)this.Object).Add(column.CreateRef());
				Reference tableRef = ((Table)((ModelObjectTreeNode)this.Node.Parent).Controller.Object).CreateRef();
				column.ParentTableRef = tableRef;
				this.OnItemChanged(this, new System.EventArgs());
			}
		}

		#endregion

	}
}